package com.hx.houtai.config;

import com.alibaba.fastjson.JSON;
import com.hx.houtai.dao.LogDao;
import com.hx.houtai.pojo.Log;
import com.hx.houtai.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;

/**
 * @author Mr.Fang
 * @description aop 日志
 * @date 2021/3/5
 */

@Slf4j
@Aspect
@Component
public class LogAspectHandler {

    @Autowired
    private LogDao logDao;

    Log logs = new Log();
    //定义要拦截的类
    @Pointcut("@annotation(com.hx.houtai.config.Log)")
    public void pointCut(){}

    @Pointcut("execution(* com.hx.houtai.service.impl..*.*(..))")
    public void pointCutTwo() {
    }

    /*
     *前置通知
     * @author 方磊
     * @date 2021/7/30
     * @param joinPoint
     * @return void
     */
    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        String declaringTypeName = signature.getDeclaringTypeName();
        String funcName = signature.getName();

        //获取请求的内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        //操作人员
        logs.setLogUser(joinPoint.getArgs()[0].toString());
        //服务端ip
        logs.setLogClientIP(this.getIpAddr(request));
        //请求的URL
        logs.setLogUrl(request.getRequestURL().toString());
        //请求的方法
        logs.setLogMethod(funcName);
        //请求的参数
        logs.setLogArgs(Arrays.toString(joinPoint.getArgs()));
    }


    /*
     *前置通知2
     * @author 方磊
     * @date 2021/8/11
      * @param joinPoint
     * @return void
     */
    @Before("pointCutTwo()")
    public void doBeforeTwo(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        String declaringTypeName = signature.getDeclaringTypeName();
        String funcName = signature.getName();
        log.info("----->执行：{}的{} 方法<-----", declaringTypeName, funcName);
    }


    /*
     *报错抓取
     * @author 方磊
     * @date 2021/7/30
     * @param joinPoint
     * @param e
     * @return void
     */
    @AfterThrowing(pointcut = "pointCut()", throwing = "e")
    public String logBeforeService(JoinPoint joinPoint, Throwable e) {
        Signature signature = joinPoint.getSignature();
        String funcName = signature.getName();
        log.info("执行方法{}出错，异常为：{}", funcName, e);
        logs.setLogResult(e.getMessage());
        this.insertLog("err");
        Result result = new Result();
        result.setCode("500");
        result.setMsg("程序出错，请联系管理员");
        return JSON.toJSON(result).toString();
    }


    /*
     *后置返回通知
     * @author 方磊
     * @date 2021/7/30
     * @param ret
     * @return void
     */
    @AfterReturning(returning = "ret", pointcut = "pointCut()")
    public void doAfterReturning(Object ret) throws Throwable {
        logs.setLogResult((String) ret);
        this.insertLog("info");
    }


    /*
     *后置通知
     * @author 方磊
     * @date 2021/7/30
     * @param joinPoint
     * @return void
     */
    @After("pointCutTwo()")
    public void doAfter(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        String funcName = signature.getName();
        log.info("----->{}方法执行完毕！<-----", funcName);
    }


    /*
     *插入日志
     * @author 方磊
     * @date 2021/7/30
     * @param type
     * @return void
     */
    public void insertLog(String type) {
        SimpleDateFormat format = new SimpleDateFormat("YYYY/MM/dd HH:mm:ss");
        logs.setLogTime(format.format(new Date()));
        logs.setLogGuid(UUID.randomUUID().toString());
        logs.setLogType(type);
        this.logDao.insertLog(logs);
    }


    /*
     *获取服务端ip
     * @author 方磊
     * @date 2021/7/30
     * @param request
     * @return java.lang.String
     */
    public String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

}
